#include "task.h"



using namespace easyWebServer;
using namespace std;

#define classInstance reflect::Singleton<ClassFactory>::getInstance().getClassFromName(idx1)

Task::Task(int fd)
    : m_fd(fd)
{
    m_request = make_shared<Request>(m_fd);
    m_response = make_shared<Response>(m_fd);
    m_fileSystem = make_shared<FileSystem>();
}

Task::~Task()
{
    Singleton<Socket>::getInstance().closeSocket(m_fd);
    m_fd = -1;
}

void Task::run()
{
    if(m_statue == TASK_OUT)
    {
        taskOut();
    }
    else if(m_statue == TASK_IN)
    {
        taskIn();
    }
}

void Task::setStatue(Statue statue)
{
    m_statue = statue;
}

int Task::getFd()
{
    return m_fd;
}

Task::Statue Task::getStatue()
{
    return m_statue;
}

void Task::taskIn()
{
    string idx1, idx2, paramter;
    m_request->recv();
    string url = (*m_request.get())["url"];
    info(url.c_str());
    if(m_fileSystem->find(Singleton<yazi::json::Json>::getInstance()["root"].asString() + url) == false)
    {
        bool ret = parseUrl(url, idx1, idx2, paramter);
        m_request->insertPair("parameter", paramter);
        ClassObject * obj = reflect::Singleton<ClassFactory>::getInstance().getClassFromName(idx1);

        if(ret == false || obj == nullptr)
        {
            idx1 = "Index";
            idx2 = "_404";
            obj = reflect::Singleton<ClassFactory>::getInstance().getClassFromName(idx1);
        }

        // reflect
        if(obj != nullptr)
        {
            obj->set<shared_ptr<Request>>("m_request", m_request);
            obj->set<shared_ptr<Response>>("m_response", m_response);
            obj->set<shared_ptr<FileSystem>>("m_fileSystem", m_fileSystem);
            obj->call(idx2);
            obj->get<shared_ptr<Request>>("m_request", m_request);
            obj->get<shared_ptr<Response>>("m_response", m_response);
            obj->get<shared_ptr<FileSystem>>("m_fileSystem", m_fileSystem);
        }
        
    }
    else
    {
        size_t fileSize = m_fileSystem->getFileSize();
        m_response->insertPair("Content-Length", to_string(fileSize));
        m_response->setContext("");
        m_response->setFileFd(m_fileSystem->getFileFd());
    }
    m_statue = TASK_OUT;
}

void Task::taskOut()
{
    m_response->send();
    m_statue = TASK_IN;
}

bool Task::parseUrl(const string & url, string & idx1, string & idx2, string & paramter)
{
    // string url_;
    // if(url.size() < 4 || url[0] != '/') return false;
    // int pos = url.find("?", 0);
    // if(pos != string::npos)
    // {
    //     paramter = url.substr(pos + 2, url.size() - pos + 1);
    //     url_ = url.substr(0, pos);
    // }
    // else
    // {
    //     url_ = url;
    // }
    // pos = url_.find("/", 0);
    // if(pos == string::npos) return false;
    // idx1 = url_.substr(1, pos - 1);
    // if(pos + 1 >= url_.size()) return false;
    // idx2 = url_.substr(pos + 1, url_.size() - pos);
    
    vector<string> urlAndParamter;
    boost::split(urlAndParamter, url, boost::is_any_of("?"));
    if(urlAndParamter.size() == 2)
    {
        paramter = urlAndParamter[1];
    }
    vector<string> idxs;
    boost::split(idxs, urlAndParamter[0], boost::is_any_of("/"));
    if(idxs.size() != 3) return false;
    idx1 = idxs[1];
    idx2 = idxs[2];
    return true;
}
